<?php
namespace App\WebSocket;

use EasySwoole\Socket\AbstractInterface\ParserInterface;
use EasySwoole\Socket\Client\WebSocket;
use EasySwoole\Socket\Bean\Caller;
use EasySwoole\Socket\Bean\Response;

use EasySwoole\EasySwoole\ServerManager;
use EasySwoole\EasySwoole\Logger;

use App\Storage\OnlineUser;

/**
 * Class WebSocketParser
 *
 * 此类是自定义的 websocket 消息解析器
 * 此处使用的设计是使用 json string 作为消息格式
 * 当客户端消息到达服务端时，会调用 decode 方法进行消息解析
 * 会将 websocket 消息 转成具体的 Class -> Action 调用 并且将参数注入
 *
 * @package App\WebSocket
 */
class WebSocketParser implements ParserInterface
{
    /**
     * decode
     * @param  string         $request    客户端原始消息
     * @param  WebSocket      $client WebSocket Client 对象
     * @return Caller         Socket  调用对象
     */
    public function decode($request, $client) : ? Caller
    {
        // 默认关闭该连接
        $data['class'] = '';
        $data['action'] = 'destroy';
        // 判断身份: 网页|终端
        $xml_parser = xml_parser_create();
        if (!xml_parse($xml_parser, $request, true)) {            
            if (gettype(json_decode($request, true)) === 'array') {
                // 如果是json格式, 交给网页服务处理
                $data['class'] = 'Web';
                $data['action'] = 'index';
            }else{
                // 非json格式, 关闭该连接
                $server = ServerManager::getInstance()->getSwooleServer();
                $server->close($client->getFd());
            }
        } else {
            $xmlob = simplexml_load_string($request, 'SimpleXMLElement', LIBXML_NOCDATA);
            $request = json_encode($xmlob);
            // Logger::getInstance()->log('request : ' . $request, Logger::LOG_LEVEL_INFO, 'RECORD');
            // 交给终端服务处理
            $data['class'] = 'Terminal';
            $data['action'] = 'index';
        }
        xml_parser_free($xml_parser);

        // 转换参数格式
        $args = ['request'=>$request];
        // new 调用者对象
        $caller =  new Caller();
        $class = '\\App\\Server\\'. ucfirst($data['class']) . 'Server';
        // 设置被调用的类
        $caller->setControllerClass($class);
        // 设置被调用的方法
        $caller->setAction($data['action'] ?? 'index');
        // 设置被调用的Args
        $caller->setArgs($args ?? []);
        return $caller;
    }
   
    /**
     * encode
     * @param  Response     $response Socket Response 对象
     * @param  WebSocket    $client   WebSocket Client 对象
     * @return string             发送给客户端的消息
     */
    public function encode(Response $response, $client) : ? string
    {
        /**
         * 这里返回响应给客户端的信息
         * 这里应当只做统一的encode操作 具体的状态等应当由 Controller处理
         */
        if (strstr($response->getMessage(), 'PONG') === false) {
            Logger::getInstance()->log(($response->getMessage()), Logger::LOG_LEVEL_INFO, 'RECORD');
        }
        return $response->getMessage();
    }
}
